package com.train.mgr.modules.biz.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.train.mgr.modules.biz.dto.response.AudioTextRespVo;
import com.train.mgr.modules.biz.dto.response.KeywordMatchResult;
import com.train.mgr.modules.biz.entity.InterfaceLog;
import com.train.mgr.modules.biz.entity.Lesson;
import com.train.mgr.modules.biz.service.IAccuracyService;
import com.train.mgr.modules.biz.service.IInterfaceLogService;
import com.train.mgr.modules.biz.utils.AccuracyScoreLevel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 准确度
 */
@Slf4j
@RequiredArgsConstructor
@Service("IAccuracyService")
public class AccuracyServiceImpl implements IAccuracyService {

    @Autowired
    private IInterfaceLogService interfaceLogService;

    /**
     * 计算准确度分数
     * @param lessonBean
     * @param audioTextBean
     * @return
     */
    @Override
    public KeywordMatchResult calAccuracyScore(Long exerciseId,Lesson lessonBean,AudioTextRespVo audioTextBean){
        long t = System.currentTimeMillis();

        //计算准确度得分
        String keywords = lessonBean.getKeywords();//获取课时关键字
        List<String> keys = Arrays.stream( Arrays.asList(keywords).get(0).split("[，,、]"))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .collect(Collectors.toList());
        KeywordMatchResult matchBean = this.matchKeyword(audioTextBean.getAudioText(), keys,false); // 输出 75.0
        matchBean.setAudioDuration(audioTextBean.getAudioDuration());//音频转换时长

        long cost = System.currentTimeMillis() - t ;
        InterfaceLog interfaceLog = new InterfaceLog();
        interfaceLog.setExerciseId(exerciseId);
        interfaceLog.setRequestSpeedTime(cost+" 毫秒");
        interfaceLog.setInterfaceType("计算准确度分数");
        interfaceLog.setRequestParam("课时配置关键字:【"+JSONObject.toJSONString(keys)+"】，未命中的关键词【"+matchBean.getMissList() +"】，命中的关键词【"+matchBean.getHitList()+"】");
        interfaceLog.setResposeResult("讯飞API转译文本:【"+audioTextBean.getAudioText()+"】");
        interfaceLogService.save(interfaceLog);

        return matchBean;
    }

    /**
     * 根据分数生成报告分析文案
     * @param score          0~100 的分数
     * @param missedKeywords 遗漏的关键词列表（可空）
     * @return 完整文案
     */
    @Override
    public String getAccuracyReport(BigDecimal score, List<String> missedKeywords) {
        if (missedKeywords == null) {
            missedKeywords = Collections.emptyList();
        }

        String missedLine = "";
        if (!missedKeywords.isEmpty()) {
            String keys = missedKeywords.stream()
                    .limit(6)          // 最多取 6 个，与模板对齐
                    .map(k -> "「" + k + "」")
                    .collect(Collectors.joining("、"));
            missedLine = "\n遗漏关键词：" + keys + "。";
        }

        String template = AccuracyScoreLevel.levelOf(score).getTemplate();
        return template + missedLine;
    }


    /**
     * 关键词匹配并返回得分 + 命中/未命中列表
     * @param text       待检查话术
     * @param keywords   系统关键词列表（允许重复，返回结果已去重且保序）
     * @param ignoreCase 是否忽略大小写
     * @return KeywordMatchResult
     */
    private KeywordMatchResult matchKeyword(String text,
                                            Collection<String> keywords,
                                            boolean ignoreCase) {

        if (text == null || keywords == null || keywords.isEmpty()) {
            return new KeywordMatchResult(BigDecimal.ZERO, Collections.emptyList(), Collections.emptyList());
        }

        String src = ignoreCase ? text.toLowerCase() : text;
        Set<String> hitSet = new LinkedHashSet<>();   // 保序去重
        Set<String> missSet = new LinkedHashSet<>();

        keywords.stream()
                .filter(Objects::nonNull)
                .map(String::trim)
                .filter(k -> !k.isEmpty())
                .forEach(k -> {
                    String key = ignoreCase ? k.toLowerCase() : k;
                    if (src.contains(key)) {
                        hitSet.add(k);      // 用原始大小写回显
                    } else {
                        missSet.add(k);
                    }
                });

        long hit = hitSet.size();
        long total = hitSet.size() + missSet.size();

        BigDecimal score = total == 0 ? BigDecimal.ZERO
                : BigDecimal.valueOf(hit)
                .divide(BigDecimal.valueOf(total), 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(1, RoundingMode.HALF_UP);

        return new KeywordMatchResult(score,
                new ArrayList<>(hitSet),
                new ArrayList<>(missSet));
    }
}
